package com.tbit.uqbike.service.rpcservice.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson.JSONObject;
import com.tbit.common.entity.view.Result;
import com.tbit.common.utils.TraceUtil;
import com.tbit.uqbike.constant.RechargeConstant;
import com.tbit.uqbike.constant.UserConstant;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.pojo.dto.CommonDTO;
import com.tbit.uqbike.object.pojo.statistics.AccountDataDaySta;
import com.tbit.uqbike.object.pojo.statistics.GramData;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.object.view.JsonResult;
import com.tbit.uqbike.object.view.NameObject;
import com.tbit.uqbike.object.view.OrderStatData;
import com.tbit.uqbike.quartz.FinancialStatisticsQuartz;
import com.tbit.uqbike.service.base.OrderCumStaService;
import com.tbit.uqbike.service.base.RedisService;
import com.tbit.uqbike.service.business.*;
import com.tbit.uqbike.service.rpcservice.PurviewService;
import com.tbit.uqbike.service.rpcservice.StatService;
import com.tbit.uqbike.webmanager.dao.capital.RideLogDetailsDao;
import com.tbit.uqbike.webmanager.dao.core.*;
import com.tbit.uqbike.webmanager.dao.log.RefundOpeLogDao;
import com.tbit.uqbike.webmanager.dao.log.RideRefundLogDao;
import com.tbit.uqbike.webmanager.dao.log.UserMealLogDao;
import com.tbit.uqbike.webmanager.dao.log.UserRefundLogDao;
import com.tbit.uqbike.webmanager.dao.stat.*;
import com.tbit.utils.DateTimeUtil;
import com.tbit.utils.DateUtil;
import com.tbit.utils.DoubleUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author MyWin E-mail:335918956@qq.com
 * @version 1.0
 * @createTime 2019-12-17 15:59
 */
@Service
@Slf4j
public class StatServiceImpl implements StatService {

    @Autowired
    private PurviewService purviewService;
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private StatDataDao statDataDao;
    @Autowired
    private RideLogService rideLogService;
    @Autowired
    private MemberFeeService memberFeeService;
    @Autowired
    private RideCardService rideCardService;
    @Autowired
    private UserService userService;
    @Autowired
    private MachineDao machineDao;
    @Autowired
    private RideOrderDayStaDao rideOrderDayStaDao;
    @Autowired
    private DepositOrderDayStaDao depositOrderDayStaDao;
    @Autowired
    private RideCardOrderDayStaDao rideCardOrderDayStaDao;
    @Autowired
    private VipCardOrderDayStaDao vipCardOrderDayStaDao;
    @Autowired
    private OrderCumStaService orderCumStaService;
    @Autowired
    private FinancialStatisticsQuartz financialStatisticsQuartz;
    @Autowired
    private RefundOpeLogDao RefundOpeLogDao;
    @Autowired
    private RideLogDao rideLogDao;
    @Autowired
    private OrderFeeAppealDao orderFeeAppealDao;
    @Autowired
    private ReconciliationDao reconciliationDao;
    @Autowired
    private UserMealLogDao userMealLogDao;
    @Autowired
    private RefundOpeLogDao refundOpeLogDao;
    @Autowired
    private RideRefundLogDao rideRefundLogDao;
    @Autowired
    private UserRefundLogDao userRefundLogDao;
    @Resource
    private RideLogDetailsDao rideLogDetailsDao;
    @Resource
    private AccountUserDao accountUserDao;
    @Autowired
    private RedisService redisService;
    @Autowired
    private AccountDayStatService accountDayStatService;

    public static void main(String[] args) {
        System.out.println(DateTimeUtil.StringToDateTime(DateTimeUtil.formatDateYMD(new Date()) + " 00:00:00").getTime());
    }

    private List<Integer> filterAccountIds(Account opAcc, List<Integer> accountIds) {
        if (null == opAcc) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        if (Objects.equals(opAcc.getType(), UserConstant.USER_FRANCHISEE) || Objects.equals(opAcc.getType(), UserConstant.USER_BRAND)
                || Objects.equals(opAcc.getType(), UserConstant.USER_AGENT) || Objects.equals(opAcc.getType(), UserConstant.USER_ADMIN)) {
            return purviewService.filterAgent(opAcc, accountIds);
        } else {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
    }

    private List<NameObject> map2List(Map<String, Integer> map) {
        List<NameObject> list = new LinkedList<>();
        for (Map.Entry<String, Integer> kv : map.entrySet()) {
            list.add(new NameObject(kv.getKey(), kv.getValue()));
        }
        return list;
    }

    @Override
    public List<NameObject> statCarStatus(LoginInfo li, List<Integer> accountIds) {
        Account opAcc = accountDao.getByAccountId(li.id);
        List<Integer> rightIds = filterAccountIds(opAcc, accountIds);
        if (rightIds.isEmpty()) {
            return new LinkedList<>();
        }
        List<BikeStatus> bsList = statDataDao.statCarStatus(rightIds);
        Map<String, Integer> map = BikeStatus.initMap();
        for (BikeStatus bs : bsList) {
            BikeStatus.statItem(map, bs);
        }
        return map2List(map);
    }

    @Override
    public List<NameObject> statCarBattery(LoginInfo li, List<Integer> accountIds) {
        Account opAcc = accountDao.getByAccountId(li.id);
        List<Integer> rightIds = filterAccountIds(opAcc, accountIds);
        if (rightIds.isEmpty()) {
            return new LinkedList<>();
        }
        List<NameCount> list = statDataDao.statCarBattery(rightIds);
        Map<String, Integer> map = new HashMap() {
            {
                put("unkonwn", 0);
                put("normal", 0);
                put("mid", 0);
                put("low", 0);
            }
        };
        for (NameCount item : list) {
            map.put(item.getName(), item.getC1());
        }
        int total = statDataDao.countCars(rightIds);
        map.put(NameObject.PRO_TOTAL, total);
        return map2List(map);
    }

    @Override
    public List<NameObject> statCarIdle(LoginInfo li, List<Integer> accountIds) {
        Account opAcc = accountDao.getByAccountId(li.id);
        List<Integer> rightIds = filterAccountIds(opAcc, accountIds);
        if (rightIds.isEmpty()) {
            return new LinkedList<>();
        }
        List<NameCount> list = statDataDao.statCarIdle(rightIds);
        Map<String, Integer> map = new HashMap() {
            {
                put("short", 0);
                put("mid", 0);
                put("long", 0);
                put("longlong", 0);
            }
        };
        for (NameCount item : list) {
            map.put(item.getName(), item.getC1());
        }
        int total = statDataDao.countCars(rightIds);
        map.put(NameObject.PRO_TOTAL, total);
        return map2List(map);
    }

    @Override
    public List<NameObject> statNewUser(LoginInfo li, List<Integer> accountIds) {
        Account opAcc = accountDao.getByAccountId(li.id);
        List<Integer> rightIds = filterAccountIds(opAcc, accountIds);
        if (rightIds.isEmpty()) {
            return new LinkedList<>();
        }
        Map<String, Integer> map = statDataDao.statNewUser(rightIds, DateTimeUtil.getYesterdayTime());
        return map2List(map);
    }

    @Override
    public Map<String, Object> statTotalData(LoginInfo li, List<Integer> accountIds, Long startDt, Long endDt) {
        Account opAcc = accountDao.getByAccountId(li.id);
        Date now = new Date();
        long nowTime = now.getTime();
        String ymd = DateTimeUtil.formatDateYMD(now);
        String time = ymd + " 00:00:00";
        long morningStartTime = DateTimeUtil.StringToDateTime(time).getTime();
        time = ymd + " 03:00:00";
        long nightStartTime = DateTimeUtil.StringToDateTime(time).getTime();
        List<Integer> rightIds = filterAccountIds(opAcc, accountIds);
        Map<String, Object> map = new HashMap<>();
        if (rightIds.isEmpty()) {
            return map;
        }
        /**检测程序，检测定时任务是否执行*/
        FinancialStatisticsQuartz.threadLocal.set(new ArrayList<>(accountIds));
        financialStatisticsQuartz.detect();
        Map<String, Object> param = new HashMap<>();
        param.put("accountIds", rightIds);
        Map<String, Object> param1 = new HashMap<>();
        NameCount vipCnt2 = new NameCount(0, 0L);
        NameCount rideCardCnt2 = new NameCount(0, 0L);
        NameCount discountCnt2 = new NameCount(0, 0L);
        NameCount rideCnt2 = new NameCount(0, 0L);

        /**如果查询的最后时间是空，或者最后的时间等于现在时间*/
        if (null == endDt || -1 != new Date(endDt).compareTo(now)) {
            param1.put("accountIds", rightIds);
            /**在晚上0点到三点统计前一天到今天此时的订单数据*/
            if (nowTime >= morningStartTime && nowTime < nightStartTime) {
                param1.put("now", DateTimeUtil.getYesterdayHHMMSS(-1, 0, 0, 0));
            } else {
                /**计算的时间不包括今天*/
                param1.put("now", DateTimeUtil.getYesterdayHHMMSS(-1));
            }
            /**获取今天的订单总额*/
            vipCnt2 = statDataDao.countVipByAidsExDt(param1);
            rideCardCnt2 = statDataDao.rideCardCount(param1);
            discountCnt2 = statDataDao.statVipLog(param1);
            rideCnt2 = statDataDao.countRideByAidsExDt(param1);
            /**查询的时间在凌晨的0点到3点内，并且查询的最后时间是昨天*/
            /**DateTimeUtil.getYesterday() : 获取前一天的年月日*/
        } else if (nowTime >= morningStartTime && nowTime < nightStartTime && DateTimeUtil.formatDateYMD(new Date(endDt)).equals(DateTimeUtil.getYesterday())) {
            param1.put("accountIds", rightIds);
            /**获取前两天的开始时间00:00:00*/
            param1.put("startDt", DateTimeUtil.getYesterdayHHMMSS(-2, 0, 0, 0));
            /**获取前一天的结束时间23：59：59*/
            param1.put("endDt", DateTimeUtil.getYesterdayHHMMSS(-1));
            /**获取今天的订单总额*/
            /**获取今天的免押会员购买的数量和金钱*/
            vipCnt2 = statDataDao.countVipByAidsExDt(param1);
            /**获取今天的骑行会员数量，和购买骑行会员的金额*/
            rideCardCnt2 = statDataDao.rideCardCount(param1);
            /**获取今天的会员数量，和会员的金额*/
            discountCnt2 = statDataDao.statVipLog(param1);
            /**获取今天的骑行费用和订单数*/
            rideCnt2 = statDataDao.countRideByAidsExDt(param1);
        }
        if (null != startDt) {
            param.put("startTime", new Date(startDt));
        }
        if (null != endDt) {
            param.put("endTime", new Date(endDt));
        }
        if (null != startDt) {
            param.put("startDt", new Date(startDt));
        }
        if (null != endDt) {
            param.put("endDt", new Date(endDt));
        }
        NameCount vipCnt1;
        NameCount rideCardCnt1;
        NameCount discountCnt1;
        NameCount rideCnt1;
        if (null == startDt && null == endDt) {
            List<NameCount> nameCounts = orderCumStaService.statTotalMoney(accountIds, 1);
            /**免押卡*//**/
            vipCnt1 = nameCounts.get(1);
            /**骑行卡*/
            rideCardCnt1 = nameCounts.get(2);
            /**vip会员卡*/
            discountCnt1 = nameCounts.get(3);
            // 骑行里面是综合，需要减去罚款的(但是骑行订单不需要减罚款订单（其中订单为c1）)
            rideCnt1 = nameCounts.get(0);
        } else {
            vipCnt1 = depositOrderDayStaDao.queryByMap(param).get(0);
            /**骑行卡*/
            rideCardCnt1 = rideCardOrderDayStaDao.queryByMap(param).get(0);
            /**vip会员卡*/
            discountCnt1 = vipCardOrderDayStaDao.queryByMap(param).get(0);
            // 骑行里面是综合，需要减去罚款的(但是骑行订单不需要减罚款订单（其中订单为c1）)
            rideCnt1 = rideOrderDayStaDao.queryByMap(param).get(0);
        }
        NameCount vipCnt = new NameCount(vipCnt1.getC1() + vipCnt2.getC1(), vipCnt1.getC2() + vipCnt2.getC2());
        // 罚款就是调度
        NameCount fineCnt = statDataDao.countFineByAidsExDt(param);
        /**骑行卡*/
        NameCount rideCardCnt = new NameCount(rideCardCnt1.getC1() + rideCardCnt2.getC1(), rideCardCnt1.getC2() + rideCardCnt2.getC2());
        /**vip会员卡*/
        NameCount discountCnt = new NameCount(discountCnt1.getC1() + discountCnt2.getC1(), discountCnt1.getC2() + discountCnt2.getC2());
        /**退款总额*/
        MoneyData moneyData = RefundOpeLogDao.totalRefundOpeLog(param).get(0);
        // 骑行里面是综合，需要减去罚款的(但是骑行订单不需要减罚款订单（其中订单为c1）)
        NameCount rideCnt = new NameCount(rideCnt1.getC1() + rideCnt2.getC1(), rideCnt1.getC2() + rideCnt2.getC2());
        rideCnt.setC2(rideCnt.getC2() - fineCnt.getC2());
        // 只有品牌或者管理员能看到这个数据
        if (Objects.equals(opAcc.getType(), UserConstant.USER_ADMIN) || Objects.equals(opAcc.getType(), UserConstant.USER_BRAND)) {
            // 押金
        }
        // 总收入 = 骑行 + 购买免押会员收入 + 调度费+vip会员卡（计算总订单时，总订单的骑行订单数包含罚款订单数）-退款的钱
        NameCount totalCnt = new NameCount(0, 0L);
        totalCnt.setC1(rideCnt.getC1() + vipCnt.getC1() + rideCardCnt.getC1() + discountCnt.getC1());
        totalCnt.setC2(rideCnt.getC2() + vipCnt.getC2() + fineCnt.getC2() + rideCardCnt.getC2() + discountCnt.getC2() - moneyData.getMoney());
        /**vip会员卡收入*/
        map.put(OrderStatData.PRO_TOTAL_REFUND_MONEY, DoubleUtils.doubleScale(moneyData.getMoney() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_REFUND_ORDER, moneyData.getNum());
        map.put(OrderStatData.PRO_TOTAL_VIP_ORDER, vipCnt.getC1());
        map.put(OrderStatData.PRO_TOTAL_VIP_MONEY, DoubleUtils.doubleScale(vipCnt.getC2() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_DISCOUNT_ORDER, discountCnt.getC1());
        map.put(OrderStatData.PRO_TOTAL_DISCOUNT_MONEY, DoubleUtils.doubleScale(discountCnt.getC2() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_FINE_ORDER, fineCnt.getC1());
        map.put(OrderStatData.PRO_TOTAL_FINE_MONEY, DoubleUtils.doubleScale(fineCnt.getC2() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_RIDE_ORDER, rideCnt.getC1());
        map.put(OrderStatData.PRO_TOTAL_RIDE_MONEY, DoubleUtils.doubleScale(rideCnt.getC2() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_ORDER, totalCnt.getC1());
        map.put(OrderStatData.PRO_TOTAL_MONEY, DoubleUtils.doubleScale(totalCnt.getC2() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_RIDECARD_MONEY, DoubleUtils.doubleScale(rideCardCnt.getC2() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_RIDECARD_ORDER, rideCardCnt.getC1());
        return map;
    }

    @Override
    public Map<String, Object> statTotalDatas(LoginInfo li, List<Integer> accountIds, Integer machineType, Long startDt, Long endDt) {
        Account opAcc = accountDao.getByAccountId(li.id);
        Date now = new Date();
        long nowTime = now.getTime();
        String ymd = DateTimeUtil.formatDateYMD(now);
        String time = ymd + " 00:00:00";
        long morningStartTime = DateTimeUtil.StringToDateTime(time).getTime();
        time = ymd + " 03:00:00";
        long nightStartTime = DateTimeUtil.StringToDateTime(time).getTime();
        List<Integer> rightIds = filterAccountIds(opAcc, accountIds);
        Map<String, Object> map = new HashMap<>();
        if (rightIds.isEmpty()) {
            return map;
        }
        //检测程序，检测定时任务是否执行
        FinancialStatisticsQuartz.threadLocal.set(new ArrayList<>(accountIds));
        financialStatisticsQuartz.detect();
        Map<String, Object> param = new HashMap<>();
        Map<String, Object> reMap = new HashMap<>();
        //订单申诉的条件
        Map<String, Object> feeAppealMap = new HashMap<>();
        reMap.put("accountIds", accountIds);
        feeAppealMap.put("accountIds", accountIds);
        if (startDt != null || endDt != null) {

            Collections.sort(accountIds, Collections.reverseOrder());
            reMap.put("brandId", accountDao.getBrandIdByAccountId(accountIds.get(0), 3));
            reMap.put("startTime", new Date(startDt));
            reMap.put("brandId", accountDao.getBrandIdByAccountId(accountIds.get(0), 3));
            reMap.put("endTime", new Date(endDt));
            reMap.put("startDt", new Date(startDt));
            reMap.put("endDt", new Date(endDt));
            feeAppealMap.put("startTime", new Date(startDt));
            feeAppealMap.put("endTime", new Date(endDt));
        }


        param.put("accountIds", accountIds);

        //骑行收入
        NameCount rideIncome;
        Long rideMoney;
        Integer rideCount;

        //免押收入
        NameCount mortgageFreeIncome;
        Long mortgageFreeMoney;
        Integer mortgageFreeCount;

        //骑行会员收入
        NameCount rideMemberIncome;
        Long rideMemberMoney;
        Integer rideMemberCount;

        //会员卡收入
        NameCount VipCartIncome;
        Long VipCartMoney;
        Integer VipCartCount;

        //优惠券收入
        Integer CouponMoney;
        Integer CouponCount;

        //优惠券退款订单
        Integer CouponRefundMoney;
        Integer CouponRefundCount;

        //会员卡退款订单
        Integer VipRefundMoney;
        Integer VipRefundCount;

        //骑行卡退款订单
        Integer RideCardRefundMoney;
        Integer RideCardRefundCount;

        //免押卡退款订单
        Integer depositCardRefundMoney;
        Integer depositCardRefundCount;

        //骑行订单退款订单
        Integer rideLogRefundMoney;
        Integer rideLogRefundCount;

        AccountDataDaySta accountDataDaySta;

        if (startDt != null && endDt != null) {
            param.put("startDt", new Date(startDt));
            param.put("endDt", new Date(endDt));
        }


        //在预统计中获取骑行收入查询时间的数据
        rideIncome = rideOrderDayStaDao.getRideOrder(param);
        rideMoney = rideIncome.getC2();
        rideCount = rideIncome.getC1();

        //在预统计中获取免押收入查询时间的数据
        mortgageFreeIncome = depositOrderDayStaDao.getMortgageFree(param);
        mortgageFreeMoney = mortgageFreeIncome.getC2();
        mortgageFreeCount = mortgageFreeIncome.getC1();

        //在预统计中获取骑行会员收入查询时间的数据
        rideMemberIncome = rideCardOrderDayStaDao.getRideMenberIncome(param);
        rideMemberMoney = rideMemberIncome.getC2();
        rideMemberCount = rideMemberIncome.getC1();

        //在预统计中获取会员卡收入查询时间的数据
        VipCartIncome = vipCardOrderDayStaDao.getVipIncome(param);
        VipCartMoney = VipCartIncome.getC2();
        VipCartCount = VipCartIncome.getC1();

        //在预统计获取优惠券、优惠券退款、会员卡退款、骑行卡退款、免押卡退款、骑行订单退款以及订单数
        param.put("type", 0);
        accountDataDaySta = reconciliationDao.getCouponIncome(param);
        //优惠券金额
        CouponMoney = accountDataDaySta.getCouponOrder();
        //优惠券退款金额
        CouponRefundMoney = accountDataDaySta.getCouponOrderRefund();
        //会员卡退款金额
        VipRefundMoney = accountDataDaySta.getVipCardRefund();
        //骑行卡退款金额
        RideCardRefundMoney = accountDataDaySta.getRideCardRefund();
        //免押卡退款金额
        depositCardRefundMoney = accountDataDaySta.getDepositCardRefund();
        //骑行订单退款金额
        rideLogRefundMoney = accountDataDaySta.getRideOrderRefund();

        param.put("type", 1);
        accountDataDaySta = reconciliationDao.getCouponIncome(param);
        //优惠券订单
        CouponCount = accountDataDaySta.getCouponOrder();
        //优惠券退款订单数
        CouponRefundCount = accountDataDaySta.getCouponOrderRefund();
        //会员卡退款订单数
        VipRefundCount = accountDataDaySta.getVipCardRefund();
        //骑行卡退款订单数
        RideCardRefundCount = accountDataDaySta.getRideCardRefund();
        //免押卡退款订单数
        depositCardRefundCount = accountDataDaySta.getDepositCardRefund();
        //骑行订单退款订单数
        rideLogRefundCount = accountDataDaySta.getRideOrderRefund();

        //没有选择时间，查询全部的数据
        if (endDt == null || endDt == -1) {
            endDt = new Date(nowTime).getTime();
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        //查询的最后时间在今天，查询今天的收入（今天没有进行预统计，查rideLog）
        if (simpleDateFormat.format(endDt).equals(DateTimeUtil.getNowTimeYMD())) {
            log.info("查询的最后时间在今天，查询今天的收入（今天没有进行预统计，查rideLog）");
            param.put("accountIds", accountIds);
            param.put("startDt", new Date(morningStartTime));
            param.put("endDt", new Date(nowTime));

            log.info("查询今天数据的条件:{}", param);

            //查询骑行收入未预统计，今天的数据
            rideIncome = rideLogDao.getRideByRidelog(param);
            rideMoney += rideIncome.getC2();
            rideCount += rideIncome.getC1();

            //查询免押收入未预统计，今天的数据
            mortgageFreeIncome = statDataDao.getVipCountMoney(param);
            mortgageFreeMoney += mortgageFreeIncome.getC2();
            mortgageFreeCount += mortgageFreeIncome.getC1();

            //查询骑行会员收入未预统计，今天的数据
            rideMemberIncome = statDataDao.getRideMember(param);
            rideMemberMoney += rideMemberIncome.getC2();
            rideMemberCount += rideMemberIncome.getC1();

            //查询会员卡收入未预统计，今天的数据
            VipCartIncome = statDataDao.getVipIncome(param);
            VipCartMoney += VipCartIncome.getC2();
            VipCartCount += VipCartIncome.getC1();

            //查询今天优惠券的数据
            CommonDTO couponDate = userMealLogDao.getCouponIncome(param);
            CouponMoney += couponDate.getMoney();
            CouponCount += couponDate.getNum();

            //查询退款数据
            //查询优惠券订单退款记录
            param.put("type", RechargeConstant.recharge_meal);
            CommonDTO couponRefund = userRefundLogDao.getRefundIncome(param);
            CouponRefundMoney += couponRefund.getMoney();
            CouponRefundCount += couponRefund.getNum();

            //查询会员卡订单退款记录
            param.put("type", RechargeConstant.recharge_vip);
            CommonDTO vipRefund = userRefundLogDao.getRefundIncome(param);
            VipRefundMoney += vipRefund.getMoney();
            VipRefundCount += vipRefund.getNum();

            //查询骑行卡订单退款记录
            param.put("type", RechargeConstant.recharge_rideCard);
            CommonDTO rideCardRefund = userRefundLogDao.getRefundIncome(param);
            RideCardRefundMoney += rideCardRefund.getMoney();
            RideCardRefundCount += rideCardRefund.getNum();


            //查询免押卡订单退款记录
            param.put("type", RechargeConstant.recharge_Mem);
            CommonDTO depositCardRefund = userRefundLogDao.getRefundIncome(param);
            depositCardRefundMoney += depositCardRefund.getMoney();
            depositCardRefundCount += depositCardRefund.getNum();

            //查询今天的骑行订单退款记录
            CommonDTO rideLogRefund = rideRefundLogDao.getRideLogRefundIncome(param);
            rideLogRefundMoney += rideLogRefund.getMoney();
            rideLogRefundCount += rideLogRefund.getNum();

        }

        //查询时当前时间在今天的0点到3点，且查询时间在昨天内，查询出今天和昨天的收入（今天和昨天的收入都没有预统计，查询rideLog）
        if ((startDt == null && nowTime >= morningStartTime && nowTime < nightStartTime) || (nowTime >= morningStartTime && nowTime < nightStartTime
                && startDt / 1000 <= DateTimeUtil.getYesterdayHHMMSS(-1, 0, 0, 0).getTime() / 1000
                && endDt / 1000 >= DateTimeUtil.getYesterdayHHMMSS(-1).getTime() / 1000)) {


            log.info("查询时当前时间在今天的0点到3点，且查询时间在昨天内，查询出今天和昨天的收入（今天和昨天的收入都没有预统计，查询rideLog）");
            log.info("查询今天的0点到3点数据的条件:{}", param);

            param.put("accountIds", accountIds);
            param.put("startDt", DateTimeUtil.getYesterdayHHMMSS(-1, 0, 0, 0));
            param.put("endDt", DateTimeUtil.getYesterdayHHMMSS(-1));


            //先在预统计里查，如果没有再从rideLog查询
            NameCount ride = rideOrderDayStaDao.getRideOrder(param);
            if (ride.getC1() == 0 && ride.getC2() == 0) {
                //查询今天0点到3点加上昨天未进行预统计的数据
                rideIncome = statDataDao.getRideByRidelog(param);
                rideMoney += rideIncome.getC2();
                rideCount += rideIncome.getC1();
            }

            //查询免押收入
            NameCount mortgageFree = depositOrderDayStaDao.getMortgageFree(param);
            if (mortgageFree.getC1() == 0 && mortgageFree.getC2() == 0) {
                mortgageFreeIncome = statDataDao.getVipCountMoney(param);
                mortgageFreeMoney += mortgageFreeIncome.getC2();
                mortgageFreeCount += mortgageFreeIncome.getC1();
            }

            //查询骑行会员收入
            NameCount rideMember = rideCardOrderDayStaDao.getRideMenberIncome(param);
            if (rideMember.getC1() == 0 && rideMember.getC2() == 0) {
                rideMemberIncome = statDataDao.getRideMember(param);
                rideMemberMoney += rideMemberIncome.getC2();
                rideMemberCount += rideMemberIncome.getC1();
            }

            //查询会员卡收入
            NameCount VipCarts = vipCardOrderDayStaDao.getVipIncome(param);
            if (VipCarts.getC1() == 0 && VipCarts.getC2() == 0) {
                VipCartIncome = statDataDao.getVipIncome(param);
                VipCartMoney += VipCartIncome.getC2();
                VipCartCount += VipCartIncome.getC1();
            }

            param.put("type", 0);
            //查询昨天的优惠券金额数据
            CommonDTO couponDate = userMealLogDao.getCouponIncome(param);
            CouponMoney += couponDate.getMoney();
            CouponCount += couponDate.getNum();

            //查询昨天的优惠券退款金额数据
            param.put("type", RechargeConstant.recharge_meal);
            CommonDTO couponRefund = userRefundLogDao.getRefundIncome(param);
            CouponRefundMoney += couponRefund.getMoney();
            CouponRefundCount += couponRefund.getNum();

            //查询昨天会员卡订单退款记录
            param.put("type", RechargeConstant.recharge_vip);
            CommonDTO vipRefund = userRefundLogDao.getRefundIncome(param);
            VipRefundMoney += vipRefund.getMoney();
            VipRefundCount += vipRefund.getNum();

            //查询昨天的骑行卡订单退款记录
            param.put("type", RechargeConstant.recharge_rideCard);
            CommonDTO rideCardRefund = userRefundLogDao.getRefundIncome(param);
            RideCardRefundMoney += rideCardRefund.getMoney();
            RideCardRefundCount += rideCardRefund.getNum();

            //查询昨天免押卡订单退款记录
            param.put("type", RechargeConstant.recharge_Mem);
            CommonDTO depositCardRefund = userRefundLogDao.getRefundIncome(param);
            depositCardRefundMoney += depositCardRefund.getMoney();
            depositCardRefundCount += depositCardRefund.getNum();

            log.info("rideLogRefundMoney========" + rideLogRefundMoney);

            //查询昨天的骑行订单退款记录
            CommonDTO rideLogRefund = rideRefundLogDao.getRideLogRefundIncome(param);
            rideLogRefundMoney += rideLogRefund.getMoney();
            rideLogRefundCount += rideLogRefund.getNum();

            log.info("rideLogRefundMoney========" + rideLogRefundMoney);
            log.info("rideLogRefund========" + rideLogRefund);

        }

        //骑行订单收入和骑行订单数
        NameCount rideOrders = new NameCount(rideCount, rideMoney);
        //免押收入和免押数量
        NameCount mortgageFrees = new NameCount(mortgageFreeCount, mortgageFreeMoney);
        //骑行会员收入和骑行会员数量
        NameCount rideMembers = new NameCount(rideMemberCount, rideMemberMoney);
        //会员卡收入和会员卡数量
        NameCount VipCarts = new NameCount(VipCartCount, VipCartMoney);
        //罚款（调度）的收入和数量
//        NameCount dispatchAmount = statDataDao.countFineByAidsExDt(reMap);
        NameCount dispatchAmount = rideLogDetailsDao.countFineByAidsExDt(reMap);
        //退款总额
        MoneyData refundAmount = RefundOpeLogDao.totalRefundOpeLog(reMap).get(0);
        //申诉订单总额
        CommonDTO feeAppealMoney = orderFeeAppealDao.getTotalMoney(feeAppealMap);
        //优惠券的收入和数量
        CommonDTO couponIncome = new CommonDTO(CouponMoney, CouponCount);
        //优惠券退款的收入和数量
        CommonDTO couponRefund = new CommonDTO(CouponRefundMoney, CouponRefundCount);
        //会员卡退款的收入和数量
        CommonDTO vipRefund = new CommonDTO(VipRefundMoney, VipRefundCount);
        //骑行卡退款的收入和数量
        CommonDTO rideCardRefund = new CommonDTO(RideCardRefundMoney, RideCardRefundCount);
        //免押卡退款的收入和数量
        CommonDTO depositCardRefund = new CommonDTO(depositCardRefundMoney, depositCardRefundCount);

        //骑行订单退款的收入和数量
        CommonDTO rideLogRefund = new CommonDTO(rideLogRefundMoney,
                rideLogRefundCount);
        /*总收入
        总数量 = 骑行订单数量（骑行订单数中包含调度数） + 骑行会员数量 +免押卡数量 + 会员卡数量
        总收入 = 骑行订单收入（骑行订单中包含调度费） + 骑行会员收入 +免押卡收入 + 会员卡收入 - 退款金额 -申诉订单总额
         */
        NameCount totalRevenue = new NameCount(rideOrders.getC1() + mortgageFrees.getC1() + rideMembers.getC1() + VipCarts.getC1() + couponIncome.getNum(),
                rideOrders.getC2() + mortgageFrees.getC2() + rideMembers.getC2() + VipCarts.getC2() + couponIncome.getMoney());

        //总退款
        NameCount totalRefund = new NameCount(rideLogRefund.getNum() + depositCardRefund.getNum() + rideCardRefund.getNum()
                + vipRefund.getNum() + couponRefund.getNum()
                , (long) (rideLogRefund.getMoney() + depositCardRefund.getMoney() + rideCardRefund.getMoney()
                + vipRefund.getMoney() + couponRefund.getMoney()));

        map.put(OrderStatData.PRO_TOTAL_REFUND_MONEY, DoubleUtils.doubleScale(refundAmount.getMoney() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_REFUND_ORDER, refundAmount.getNum());
        map.put(OrderStatData.PRO_TOTAL_VIP_ORDER, mortgageFrees.getC1());
        map.put(OrderStatData.PRO_TOTAL_VIP_MONEY, DoubleUtils.doubleScale(mortgageFrees.getC2() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_DISCOUNT_ORDER, VipCarts.getC1());
        map.put(OrderStatData.PRO_TOTAL_DISCOUNT_MONEY, DoubleUtils.doubleScale(VipCarts.getC2() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_FINE_ORDER, dispatchAmount.getC1());
        map.put(OrderStatData.PRO_TOTAL_FINE_MONEY, DoubleUtils.doubleScale(dispatchAmount.getC2() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_RIDE_ORDER, rideOrders.getC1());
        map.put(OrderStatData.PRO_TOTAL_RIDE_MONEY, DoubleUtils.doubleScale(rideOrders.getC2() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_ORDER, totalRevenue.getC1());
        map.put(OrderStatData.PRO_TOTAL_MONEY, DoubleUtils.doubleScale(totalRevenue.getC2() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_RIDECARD_MONEY, DoubleUtils.doubleScale(rideMembers.getC2() / 100.0));
        map.put(OrderStatData.PRO_TOTAL_RIDECARD_ORDER, rideMembers.getC1());
        map.put("totalCouponMoney", couponIncome.getMoney() / 100.0);
        map.put("totalCouponCount", couponIncome.getNum());
        map.put("totalCouponRefundMoney", couponRefund.getMoney() / 100.0);
        map.put("totalCouponRefundCount", couponRefund.getNum());
        map.put("totalVipRefundMoney", vipRefund.getMoney() / 100.0);
        map.put("totalVipRefundCount", vipRefund.getNum());
        map.put("totalRideCardRefundMoney", rideCardRefund.getMoney() / 100.0);
        map.put("totalRideCardRefundCount", rideCardRefund.getNum());
        map.put("totalDepositCardRefundMoney", depositCardRefund.getMoney() / 100.0);
        map.put("totalDepositCardRefundCount", depositCardRefund.getNum());
        map.put("totalRideLogRefundMoney", rideLogRefund.getMoney() / 100.0);
        map.put("totalRideLogRefundCount", rideLogRefund.getNum());
        map.put("totalRefundMoney", totalRefund.getC2() / 100.0);
        map.put("totalRefundCount", totalRefund.getC1());

        return map;
    }

    @Override
    public Double statTotalMoney(LoginInfo li, List<Integer> accountIds, Long startDt, Long endDt) {
        Account opAcc = accountDao.getByAccountId(li.id);
        Date now = new Date();
        long nowTime = now.getTime();
        String ymd = DateTimeUtil.formatDateYMD(now);
        String time = ymd + " 00:00:00";
        long morningStartTime = DateTimeUtil.StringToDateTime(time).getTime();
        time = ymd + " 03:00:00";
        long nightStartTime = DateTimeUtil.StringToDateTime(time).getTime();
        List<Integer> rightIds = filterAccountIds(opAcc, accountIds);
        if (rightIds.isEmpty()) {
            return 0.0;
        }
        /**检测程序，检测定时任务是否执行*/
        FinancialStatisticsQuartz.threadLocal.set(new ArrayList<>(accountIds));
        financialStatisticsQuartz.detect();
        Map<String, Object> param = new HashMap<>();
        Map<String, Object> param1 = new HashMap<>();
        param.put("accountIds", rightIds);
        NameCount vipCnt2 = new NameCount(0, 0L);
        NameCount rideCardCnt2 = new NameCount(0, 0L);
        NameCount discountCnt2 = new NameCount(0, 0L);
        NameCount rideCnt2 = new NameCount(0, 0L);
        if (null == endDt || -1 != new Date(endDt).compareTo(new Date())) {
            param1.put("accountIds", rightIds);
            if (nowTime >= morningStartTime && nowTime < nightStartTime) {
                /**在晚上0点到三点统计前一天到今天此时的订单数据*/
                param1.put("now", DateTimeUtil.getYesterdayHHMMSS(-1, 0, 0, 0));
            } else {
                param1.put("now", DateTimeUtil.getYesterdayHHMMSS(-1));
            }
            /**获取今天的订单总额*/
            vipCnt2 = statDataDao.countVipByAidsExDt(param1);
            rideCardCnt2 = statDataDao.rideCardCount(param1);
            discountCnt2 = statDataDao.statVipLog(param1);
            rideCnt2 = statDataDao.countRideByAidsExDt(param1);
        } else if (nowTime >= morningStartTime && nowTime < nightStartTime && DateTimeUtil.formatDateYMD(new Date(endDt)).equals(DateTimeUtil.getYesterday())) {
            param1.put("accountIds", rightIds);
            param1.put("startDt", DateTimeUtil.getYesterdayHHMMSS(-1, 0, 0, 0));
            param1.put("endDt", DateTimeUtil.getYesterdayHHMMSS(-1));
            /**获取今天的订单总额*/
            vipCnt2 = statDataDao.countVipByAidsExDt(param1);
            rideCardCnt2 = statDataDao.rideCardCount(param1);
            discountCnt2 = statDataDao.statVipLog(param1);
            rideCnt2 = statDataDao.countRideByAidsExDt(param1);
        }
        if (null != startDt) {
            param.put("startTime", new Date(startDt));
        }
        if (null != endDt) {
            param.put("endTime", new Date(endDt));
        }
        if (null != startDt) {
            param.put("startDt", new Date(startDt));
        }
        if (null != endDt) {
            param.put("endDt", new Date(endDt));
        }
        // 免押会员
        NameCount vipCnt1 = depositOrderDayStaDao.queryByMap(param).get(0);
        NameCount vipCnt = new NameCount(vipCnt1.getC1() + vipCnt2.getC1(), vipCnt1.getC2() + vipCnt2.getC2());
        // 罚款就是调度
        NameCount fineCnt = statDataDao.countFineByAidsExDt(param);
        /**退款总额*/
        MoneyData moneyData = RefundOpeLogDao.totalRefundOpeLog(param).get(0);
        /**骑行卡*/
        NameCount rideCardCnt1 = rideCardOrderDayStaDao.queryByMap(param).get(0);
        NameCount rideCardCnt = new NameCount(rideCardCnt1.getC1() + rideCardCnt2.getC1(), rideCardCnt1.getC2() + rideCardCnt2.getC2());
        /**vip会员卡*/
        NameCount discountCnt1 = vipCardOrderDayStaDao.queryByMap(param).get(0);
        NameCount discountCnt = new NameCount(discountCnt1.getC1() + discountCnt2.getC1(), discountCnt1.getC2() + discountCnt2.getC2());
        // 骑行里面是综合，需要减去罚款的(但是骑行订单不需要减罚款订单（其中订单为c1）以及退款的钱)
        NameCount rideCnt1 = rideOrderDayStaDao.queryByMap(param).get(0);
        NameCount rideCnt = new NameCount(rideCnt1.getC1() + rideCnt2.getC1(), rideCnt1.getC2() + rideCnt2.getC2());
        rideCnt.setC2(rideCnt.getC2() - fineCnt.getC2());
        // 总收入 = 骑行 + 购买免押会员收入 + 调度费
        NameCount totalCnt = new NameCount(0, 0L);
        totalCnt.setC1(rideCnt.getC1() + vipCnt.getC1() + rideCardCnt.getC1() + discountCnt.getC1());
        totalCnt.setC2(rideCnt.getC2() + vipCnt.getC2() + fineCnt.getC2() + rideCardCnt.getC2() + discountCnt.getC2() - moneyData.getMoney());
        return totalCnt.getC2() / 100.0;
    }


    @Override
    public Map<String, Object> statCurrentData(LoginInfo li, List<Integer> accountIds) {
        Long start = DateUtil.getDate(li.zone);
        return statTotalData(li, accountIds, start, start + DateUtil.DAY_MS);
    }


    /**
     * 导出总数据，导出移除，所以不修改
     */
    @Override
    public List<OrderStatData> statTotalByArea(LoginInfo li, List<Integer> accountIds, Long startDt, Long endDt) {
        Account opAcc = accountDao.getByAccountId(li.id);
        List<Integer> rightIds = filterAccountIds(opAcc, accountIds);
        if (rightIds.isEmpty()) {
            return new LinkedList<>();
        }
        Map<String, Object> param = new HashMap<>();
        param.put("accountIds", rightIds);
        Date start = null, end = null;
        if (null != startDt) {
            start = new Date(startDt);
            param.put("startDt", start);
        }
        if (null == endDt) {
            endDt = System.currentTimeMillis();
        }
        end = new Date(endDt);
        param.put("endDt", end);

        Map<Integer, OrderStatData> map = new HashMap<>();
        List<OrderStatData> list = new LinkedList<>();
        for (Integer id : rightIds) {
            OrderStatData item = OrderStatData.getNormalItem();
            list.add(item);
            map.put(id, item);
        }

        OrderStatData first = list.get(0);
        // 只有品牌或者管理员能看到这个数据
        if (Objects.equals(opAcc.getType(), UserConstant.USER_BRAND) || Objects.equals(opAcc.getType(), UserConstant.USER_ADMIN)) {
            // 押金
            NameCount depositCnt = statDataDao.countDepositByAidsExDt(param);
            first.totalDepositOrder = depositCnt.getC1();
            first.totalDepositMoney = depositCnt.getC2();
            // 充值余额
            NameCount rechargeCnt = statDataDao.countRechargeByAidsExDt(param);
            first.totalRechargeOrder = rechargeCnt.getC1();
            first.totalRechargeMoney = rechargeCnt.getC2();
        }
        // 免押会员
        List<NameCount> vipCnts = statDataDao.countVipByAidsExDtGroupAid(param);
        for (NameCount item : vipCnts) {
            OrderStatData osd = map.get(item.getId());
            osd.totalVipOrder = item.getC1();
            osd.totalVipMoney = item.getC2();
        }
        // 罚款就是调度
        List<NameCount> fineCnts = statDataDao.countFineByAidsExDtGroupAid(param);
        for (NameCount item : fineCnts) {
            OrderStatData osd = map.get(item.getId());
            osd.totalFineOrder = item.getC1();
            osd.totalFineMoney = item.getC2();
        }
        // 骑行里面是综合，需要减去罚款的
        List<NameCount> rideCnts = statDataDao.countRideByAidsExDtGroupAid(param);
        for (NameCount item : rideCnts) {
            OrderStatData osd = map.get(item.getId());
            osd.totalRideOrder = item.getC1();
            osd.totalRideMoney = item.getC2() - osd.totalFineMoney;
        }
        // 总收入 = 骑行 + 购买免押会员收入 + 调度费
        for (OrderStatData osd : list) {
            osd.totalOrder = osd.totalRideOrder + osd.totalVipOrder + osd.totalFineOrder;
            osd.totalMoney = osd.totalRideMoney + osd.totalVipMoney + osd.totalFineMoney;
        }
        // 车辆数
        List<NameCount> bikeCnts = statDataDao.countCarsGroupAid(param);
        for (NameCount item : bikeCnts) {
            OrderStatData osd = map.get(item.getId());
            osd.name = item.getName();
            osd.totalBike = item.getC1();
            osd.end = DateUtil.YMD_.format(end);
            double totalDays = 0;
            if (null != start) {
                osd.start = DateUtil.YMD_.format(start);
                totalDays = DateTimeUtil.getDiffDay(start, end);
            } else {
                osd.start = DateUtil.YMD_.format(item.getDt());
                totalDays = DateTimeUtil.getDiffDay(item.getDt(), end);
            }
            int days = (int) (Math.ceil(totalDays));
            if (days <= 0) {
                days = 1;
            }
            osd.moneyPerCarDay = osd.totalMoney / osd.totalBike / days;
            osd.orderPerCarDay = osd.totalOrder * 1.0 / osd.totalBike / days;
            BigDecimal bdOrder = new BigDecimal(osd.moneyPerCarDay);
            osd.orderPerCarDay = bdOrder.setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        }
        return list;
    }

    @Override
    /**
     * 统计的是已支付的订单和总数
     * */
    public List<NameObject> statMoneyByType(List<Integer> accountIds, Long startDt, Long endDt,
                                            Integer type) {
        List<NameObject> list = new LinkedList<>();
        Map<String, Object> param = new HashMap<>();
        Date now = new Date();
        long nowTime = now.getTime();
        String ymd = DateTimeUtil.formatDateYMD(now);
        String time = ymd + " 00:00:00";
        long morningStartTime = DateTimeUtil.StringToDateTime(time).getTime();
        time = ymd + " 03:00:00";
        long nightStartTime = DateTimeUtil.StringToDateTime(time).getTime();
        param.put("accountIds", accountIds);
        if (null != startDt) {
            param.put("startTime", new Date(startDt));
        }
        if (null != endDt) {
            param.put("endTime", new Date(endDt));
        }
        Map<String, Object> param1 = new HashMap<>();
        param.put("accountIds", accountIds);
        NameCount vipCnt2 = new NameCount(0, 0L);
        NameCount rideCardCnt2 = new NameCount(0, 0L);
        NameCount discountCnt2 = new NameCount(0, 0L);
        NameCount rideCnt2 = new NameCount(0, 0L);
        if (-1 != new Date(endDt).compareTo(new Date())) {
            param1.put("accountIds", accountIds);
            if (nowTime >= morningStartTime && nowTime < nightStartTime) {
                /**在晚上0点到三点统计前一天到今天此时的订单数据*/
                param1.put("now", DateTimeUtil.getYesterdayHHMMSS(-1, 0, 0, 0));
            } else {
                param1.put("now", DateTimeUtil.getYesterdayHHMMSS(-1));
            }
            /**获取当天订单总额*/
            vipCnt2 = statDataDao.countVipByAidsExDt(param1);
            rideCardCnt2 = statDataDao.rideCardCount(param1);
            discountCnt2 = statDataDao.statVipLog(param1);
            rideCnt2 = statDataDao.countRideByAidsExDt(param1);
        } else if (nowTime >= morningStartTime && nowTime < nightStartTime && DateTimeUtil.formatDateYMD(new Date(endDt)).equals(DateTimeUtil.getYesterday())) {
            param1.put("accountIds", accountIds);
            param1.put("startDt", DateTimeUtil.getYesterdayHHMMSS(-1, 0, 0, 0));
            param1.put("endDt", DateTimeUtil.getYesterdayHHMMSS(-1));
            /**获取今天的订单总额*/
            vipCnt2 = statDataDao.countVipByAidsExDt(param1);
            rideCardCnt2 = statDataDao.rideCardCount(param1);
            discountCnt2 = statDataDao.statVipLog(param1);
            rideCnt2 = statDataDao.countRideByAidsExDt(param1);
        }
        // 免押会员
        NameCount vipCnt = depositOrderDayStaDao.queryByMap(param).get(0);
        /**骑行卡*/
        NameCount rideCardCnt = rideCardOrderDayStaDao.queryByMap(param).get(0);
        /**vip会员卡*/
        NameCount discountCnt = vipCardOrderDayStaDao.queryByMap(param).get(0);
        NameCount rideCnt = rideOrderDayStaDao.queryByMap(param).get(0);
        Integer ride;
        Integer card;
        Integer mem;
        Integer vip;
        if (type == 0) {
            ride = Math.toIntExact(rideCnt.getC2() + rideCnt2.getC2());
            card = Math.toIntExact(rideCardCnt.getC2() + rideCardCnt2.getC2());
            mem = Math.toIntExact(discountCnt.getC2() + discountCnt2.getC2());
            vip = Math.toIntExact(vipCnt.getC2() + vipCnt2.getC2());
        } else {
            ride = Math.toIntExact(rideCnt.getC1() + rideCnt2.getC1());
            card = Math.toIntExact(rideCardCnt.getC1() + rideCardCnt2.getC1());
            mem = Math.toIntExact(discountCnt.getC1() + discountCnt2.getC1());
            vip = Math.toIntExact(vipCnt.getC1() + vipCnt2.getC1());
        }
//        Integer ride = rideLogService.getRideMoneyByTime(accountIds,DateTimeUtil.DateTimeToString(new Date(startDt)),DateTimeUtil.DateTimeToString(new Date(endDt)),type);
        NameObject rideObject = new NameObject("ride", ride);
        list.add(rideObject);
//        Integer card = rideCardService.getMoneyByTime(accountIds,DateTimeUtil.DateTimeToString(new Date(startDt)),DateTimeUtil.DateTimeToString(new Date(endDt)),type);
        NameObject cardObject = new NameObject("card", card);
        list.add(cardObject);
//        Integer mem = memberFeeService.getMoneyByTime(accountIds,DateTimeUtil.DateTimeToString(new Date(startDt)),DateTimeUtil.DateTimeToString(new Date(endDt)),type);
        NameObject memObject = new NameObject("mem", mem);
        list.add(memObject);
        NameObject vipObject = new NameObject("mem", vip);
        list.add(vipObject);
        return list;
    }

    @Override
    public List<GramData> statMoByTime(List<Integer> accountIds, Long startDt, Long endDt,
                                       Integer type, Integer selectType) {
        List<GramData> list = new LinkedList<>();
        /**骑行订单数据*/
        List<StatPark> rideStat = rideLogService.statByType(accountIds, DateTimeUtil.DateTimeToString(new Date(startDt)), DateTimeUtil.DateTimeToString(new Date(endDt)), type);
        /**骑行卡订单数据*/
        List<StatPark> cardStat = rideCardService.statByType(accountIds, DateTimeUtil.DateTimeToString(new Date(startDt)), DateTimeUtil.DateTimeToString(new Date(endDt)), type);
        /**免押会员订单数据*/
        List<StatPark> memberStat = memberFeeService.statByType(accountIds, DateTimeUtil.DateTimeToString(new Date(startDt)), DateTimeUtil.DateTimeToString(new Date(endDt)), type);
        /**selectType 0 订单收入 1 订单量*/
        if (selectType == 0) {
            if (type == 0) {
                for (int i = 0; i < rideStat.size(); i++) {
                    GramData gramData = new GramData();
                    gramData.setName(rideStat.get(i).getName());
                    gramData.setRideMoney(rideStat.get(i).getMoney());
                    gramData.setCardMoney(cardStat.get(i).getMoney());
                    gramData.setMemberMoney(memberStat.get(i).getMoney());
                    list.add(gramData);
                }
            } else {
                List<String> stringDate = DateTimeUtil.getDateArrByMonth(new Date(startDt), new Date(endDt));
                for (String string : stringDate) {
                    GramData gramData = new GramData(0, 0, 0);
                    gramData.setName(string);
                    /**骑行订单数据*/
                    for (StatPark s : rideStat) {
                        if (s.getName().equals(string)) {
                            gramData.setRideMoney(s.getMoney());
                        }
                    }
                    /**骑行卡订单数据*/
                    for (StatPark s : cardStat) {
                        if (s.getName().equals(string)) {
                            gramData.setCardMoney(s.getMoney());
                        }
                    }
                    /**免押会员订单数据*/
                    for (StatPark s : memberStat) {
                        if (s.getName().equals(string)) {
                            gramData.setMemberMoney(s.getMoney());
                        }
                    }
                    list.add(gramData);
                }
            }
        } else if (selectType == 1) {
            if (type == 0) {
                for (int i = 0; i < rideStat.size(); i++) {
                    GramData gramData = new GramData();
                    gramData.setName(rideStat.get(i).getName());
                    gramData.setRideMoney(rideStat.get(i).getTotal());
                    gramData.setCardMoney(cardStat.get(i).getTotal());
                    gramData.setMemberMoney(memberStat.get(i).getTotal());
                    list.add(gramData);
                }
            } else {
                List<String> stringDate = DateTimeUtil.getDateArrByMonth(new Date(startDt), new Date(endDt));
                for (String string : stringDate) {
                    GramData gramData = new GramData(0, 0, 0);
                    gramData.setName(string);
                    /**骑行订单数据*/
                    for (StatPark s : rideStat) {
                        if (s.getName().equals(string)) {
                            gramData.setRideMoney(s.getTotal());
                        }
                    }
                    /**骑行卡订单数据*/
                    for (StatPark s : cardStat) {
                        if (s.getName().equals(string)) {
                            gramData.setCardMoney(s.getTotal());
                        }
                    }
                    /**免押会员订单数据*/
                    for (StatPark s : memberStat) {
                        if (s.getName().equals(string)) {
                            gramData.setMemberMoney(s.getTotal());
                        }
                    }
                    list.add(gramData);
                }
            }
        }

        return list;
    }

    @Override
    public List<NameObject> groupByBirth(List<Integer> accountIds) {
        return userService.groupByBirth(accountIds);
    }

    @Override
    public List<NameObject> groupBySex(List<Integer> accountIds) {
        return userService.groupBySex(accountIds);
    }

    @Override
    public List<NameObject> statUserByType(List<Integer> accountIds, Long startDt, Long endDt, Integer type) {
        return userService.statByTypePlus(accountIds, new Date(startDt), new Date(endDt), type);
    }

    @Override
    public JSONObject statByBid(Integer accountId) {
        JSONObject jsonObject = new JSONObject();
        /**type 为 null是用户总数，为1是总金额，为2是总欠款*/
        Integer userTotal = userService.countByType(null, accountId);
        jsonObject.put("userTotal", userTotal);
        Integer userTotalMoney = userService.countByType(1, accountId);
        if (userTotalMoney == null) {
            userTotalMoney = 0;
        }
        jsonObject.put("userTotalMoney", userTotalMoney * 1D / 100);
        Integer userArrMoney = userService.countByType(2, accountId);
        if (userArrMoney == null) {
            userArrMoney = 0;
        }
        jsonObject.put("userArrMoney", userArrMoney * 1D / 100);
        /**平台总押金以及押金人数*/
        DepositCount depositCount = userService.countDeposit(accountId);
        if (depositCount.getMoney() == null) {
            depositCount.setMoney(0);
        }
        jsonObject.put("depositMoney", depositCount.getMoney() * 1D / 100);
        jsonObject.put("depositTotal", depositCount.getTotal());
        /**平台总设备数*/
        Integer machineTotal = machineDao.countByBID(accountId);
        jsonObject.put("machineTotal", machineTotal);
        /**平台在线设备总数*/
        Integer onlineMachineTotal = machineDao.countOnlineMachineByBid(accountId, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), 1800L);
        jsonObject.put("onlineMachineTotal", onlineMachineTotal);
        return jsonObject;
    }

    @Override
    public List<NameObject> statCarStatusV2(LoginInfo li, List<Integer> idList) {
        //todo 暂时做缓存，避免查询频繁导致程序oom，后续优化
//        String key = RedisConstant.MACHINE_STAT_CATCH + JSONObject.toJSONString(idList);
//        String statCatch = redisService.get(key);
//        if (statCatch != null) {
//            log.info("{}重复查询，返回缓存信息", JSONObject.toJSONString(idList));
//            return JSONObject.parseObject(statCatch, new TypeReference<List<NameObject>>() {});
//        }
        Account opAcc = accountDao.getByAccountId(li.id);
        List<Integer> accountIds = filterAccountIds(opAcc, idList);
        if (accountIds.isEmpty()) {
            return new LinkedList<>();
        }
        Map<String, Integer> map = new HashMap<>();
        //总车辆
        List<Integer> machineIds = machineDao.selectMachineIdsByAccountIds(accountIds);
        map.put(BikeStatus.PRO_TOTAL, machineIds.size());
        //丢失车辆
        List<Integer> loseMachineIds = machineIds.isEmpty() ? new ArrayList<>() : machineDao.selectLoseMachineIds(machineIds);
        map.put("lose", loseMachineIds.size());
        machineIds.removeAll(loseMachineIds);
        //未投放车辆
        List<Integer> unPutInMachineIds = machineIds.isEmpty() ? new ArrayList<>() : machineDao.selectUnPutInMachineIds(machineIds);
        map.put("unPutIn", unPutInMachineIds.size());
        machineIds.removeAll(unPutInMachineIds);
        //骑行中车辆
        List<Integer> isUseMachineIds = machineIds.isEmpty() ? new ArrayList<>() : machineDao.selectIsUserMachineIds(machineIds);
        map.put(BikeStatus.PRO_USE, isUseMachineIds.size());
        machineIds.removeAll(isUseMachineIds);
        //故障车辆
        List<Integer> faultMachineIds = machineIds.isEmpty() ? new ArrayList<>() : machineDao.selectFaultMachineIds(machineIds);
        map.put(BikeStatus.PRO_FAULT, faultMachineIds.size());
        machineIds.removeAll(faultMachineIds);
        //异常车辆(无信号/超区/电池异常)
        List<Integer> abnormalMachineIds = machineIds.isEmpty() ? new ArrayList<>() : machineDao.selectAbnormalMachineIds(machineIds);
        map.put(BikeStatus.PRO_ABNORMAL, abnormalMachineIds.size());
        machineIds.removeAll(abnormalMachineIds);
        //缺电车辆
        List<Integer> powerShortageMachineIds = machineIds.isEmpty() ? new ArrayList<>() : machineDao.selectPowerShortageMachineIds(machineIds);
        map.put("powerShortage", powerShortageMachineIds.size());
        machineIds.removeAll(powerShortageMachineIds);
        map.put(BikeStatus.PRO_NORMAL, machineIds.size());
        List<NameObject> nameObjects = map2List(map);
//        redisService.add(key, JSON.toJSONString(nameObjects), 60 * 10);
        return nameObjects;
    }

    /**
     * 提供给运维端获取罚款费用
     * @param map 区域id accountIds 区域id集合 startDt 开始时间 endDt 结束时间
     * @return result
     */
    @Override
    public Result<Object> getFineMoney(Map<String, Object> map) {
        return Result.success(rideLogDetailsDao.countFineByAidsExDt(map));
    }

    /**
     * 产生订单折线图
     * @param statLineChartByPic statLineChartByPic
     * @return result
     */
    @Override
    public JsonResult hasOrder(StatLineChartByPic statLineChartByPic) {
        Date start = new Date(statLineChartByPic.getStartTime());
        Date end = new Date(statLineChartByPic.getEndTime());
        if (cn.hutool.core.date.DateUtil.betweenDay(start, end, true) > 30) {
            return JsonResult.fail("时间范围过大", TraceUtil.getTraceIdByLocal());
        }
        //根据日期获取所有日期
        String startDate = cn.hutool.core.date.DateUtil.format(start, "yyyy-MM-dd");
        String endDate = cn.hutool.core.date.DateUtil.format(end, "yyyy-MM-dd");
        List<String> allDatesBetween = getAllDatesBetween(cn.hutool.core.date.DateUtil.parse(startDate, "yyyy-MM-dd"), cn.hutool.core.date.DateUtil.parse(endDate, "yyyy-MM-dd"));
        //获取区域车辆订单数
        List<MachineGroup> accountList = rideLogDao.getHasOrderByAccount(statLineChartByPic.getAccountId(), start, end);
        Map<String, MachineGroup> map = new HashMap<>();
        accountList.forEach(x -> {
            map.put(x.getDate(), x);
        });
        List<StatPark> list = new ArrayList<>();
        for (String date : allDatesBetween) {
            StatPark statPark = new StatPark();
            statPark.setName(date);
            statPark.setHaveOrderCount(Objects.isNull(map.get(date)) ? 0 : map.get(date).getHasOrderCount());
            //兼容前端 没有补0
            statPark.setMoney(0);
            statPark.setTotal(0);
            statPark.setPutInMachineCount(0);
            list.add(statPark);
        }
        //获取该区域下所有分区、对应分区下所有车辆数
        List<Region> regionList = accountUserDao.getRegionId(statLineChartByPic.getAccountId());
        List<MachineGroup> groupList = rideLogDao.getHasOrderByRegion(statLineChartByPic.getAccountId(), start, end, regionList.stream().map(Region::getRegionId).collect(Collectors.toSet()));
        //转成Map<分区id,MachineGroup>
        Map<Integer, List<MachineGroup>> regionMap = new HashMap<>();
        for (MachineGroup machineGroup : groupList) {
            List<MachineGroup> groups = regionMap.get(machineGroup.getRegionId());
            if (CollectionUtil.isEmpty(groups)) {
                groups = new ArrayList<>();
                groups.add(machineGroup);
                regionMap.put(machineGroup.getRegionId(), groups);
            } else {
                groups.add(machineGroup);
            }
        }

        List<StatParkDTO> statParkDTOList = new ArrayList<>();
        for (Region region : regionList) {
            List<MachineGroup> groups = regionMap.get(region.getRegionId());
            StatParkDTO statParkDTO = new StatParkDTO();
            statParkDTO.setRegionId(region.getRegionId());
            statParkDTO.setRegionName(region.getRegionName());

            Map<String, Integer> groupMap = new HashMap<>();
            if (CollectionUtil.isNotEmpty(groups)) {
                groups.forEach(x -> {
                    groupMap.put(x.getDate(), x.getHasOrderCount());
                });
            }

            List<StatPark> parkList = new ArrayList<>();
            for (String date : allDatesBetween) {
                StatPark statPark = new StatPark();
                statPark.setRegionId(region.getRegionId());
                statPark.setRegionName(region.getRegionName());
                statPark.setName(date);
                statPark.setHaveOrderCount(groupMap.get(date) == null ? 0 : groupMap.get(date));
                statPark.setMoney(0);
                statPark.setTotal(0);
                parkList.add(statPark);
            }
            statParkDTO.setStatParkList(parkList);
            statParkDTOList.add(statParkDTO);
        }
        return JsonResult.ok(statParkDTOList, list);
    }

    /**
     * 获取开始日期和结束日期之间的所有天数
     */
    public static List<String> getAllDatesBetween(DateTime startDate, DateTime endDate) {
        List<String> dates = new ArrayList<>();
        DateTime current = startDate;
        while (!current.isAfter(endDate)) {
            dates.add(current.toString("yyyy-MM-dd"));
            current = current.offsetNew(DateField.DAY_OF_MONTH, 1); // 增加一天
        }

        return dates;
    }


    @Override
    public List<NameObject> statCarStatusV3(LoginInfo li, List<Integer> idList) {
        Account opAcc = accountDao.getByAccountId(li.id);
        List<Integer> accountIds = filterAccountIds(opAcc, idList);
        if (accountIds.isEmpty()) {
            return new LinkedList<>();
        }
        Map<String, Integer> data = machineDao.getStatData(accountIds);

        List<NameObject> nameObjects = map2List(data);
        return nameObjects;
    }

    @Override
    public Integer todayNewUser(List<Integer> idList) {
        return accountDayStatService.todayNewUser(idList);
    }
}
